home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_se / run_feature.e < prev    next >
Text File  |  2000-03-25  |  34KB  |  1,196 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
  4. --                       http://SmallEiffel.loria.fr
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
  11. -- for  more  details.  You  should  have  received a copy of the GNU General
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. deferred class RUN_FEATURE
  17.    --
  18.    -- A feature at run time : assertions collected and only run types.
  19.    --
  20.    --   RUN_FEATURE_1  : constant attribute.
  21.    --   RUN_FEATURE_2  : attribute.
  22.    --   RUN_FEATURE_3  : procedure.
  23.    --   RUN_FEATURE_4  : function.
  24.    --   RUN_FEATURE_5  : once procedure.
  25.    --   RUN_FEATURE_6  : once function.
  26.    --   RUN_FEATURE_7  : external procedure.
  27.    --   RUN_FEATURE_8  : external function.
  28.    --   RUN_FEATURE_9  : deferred routine.
  29.    --   RUN_FEATURE_10 : Precursor procedure.
  30.    --   RUN_FEATURE_11 : Precursor function.
  31.    --
  32.  
  33. inherit GLOBALS;
  34.  
  35. feature {NONE}
  36.  
  37.    clients_memory: CLIENT_LIST;
  38.  
  39. feature
  40.  
  41.    current_type: TYPE;
  42.          -- The type of Current in the corresponding feature.
  43.  
  44.    name: FEATURE_NAME;
  45.          -- Final name (the only one really used) of the feature.
  46.  
  47.    base_feature: E_FEATURE is
  48.          -- Original base feature definition.
  49.       deferred
  50.       end;
  51.  
  52.    arguments: FORMAL_ARG_LIST is
  53.          -- Runnable arguments list if any.
  54.       deferred
  55.       end;
  56.  
  57.    result_type: TYPE is
  58.          -- Runnable Result type if any.
  59.       deferred
  60.       end;
  61.  
  62.    require_assertion: RUN_REQUIRE is
  63.          -- Runnable collected require assertion if any.
  64.       deferred
  65.       end;
  66.  
  67.    local_vars: LOCAL_VAR_LIST is
  68.          -- Runnable local var list if any.
  69.       deferred
  70.       end;
  71.  
  72.    routine_body: COMPOUND is
  73.          -- Runnable routine body if any.
  74.       deferred
  75.       end;
  76.  
  77.    ensure_assertion: E_ENSURE is
  78.          -- Runnable collected ensure assertion if any.
  79.       deferred
  80.       end;
  81.  
  82.    rescue_compound: COMPOUND is
  83.          -- Runnable rescue compound if any.
  84.       deferred
  85.       end;
  86.  
  87.    is_once_procedure: BOOLEAN is
  88.      -- This is not only true for RUN_FEATURE_5, but it may be also 
  89.      -- true when some once procedure is wrapped (RUN_FEATURE_10).
  90.       deferred
  91.       ensure
  92.      Result implies result_type = Void
  93.       end;
  94.  
  95.    is_once_function: BOOLEAN is
  96.      -- This is not only true for RUN_FEATURE_6, but it may be also 
  97.      -- true when some once function is wrapped (RUN_FEATURE_11).
  98.       deferred
  99.       ensure
  100.      Result implies result_type /= Void
  101.       end;
  102.  
  103.    is_deferred: BOOLEAN is
  104.       deferred
  105.       end;
  106.  
  107.    is_pre_computable: BOOLEAN is
  108.       require
  109.          small_eiffel.is_ready
  110.       deferred
  111.       end;
  112.  
  113.    can_be_dropped: BOOLEAN is
  114.      -- If calling has no side effect at all.
  115.       require
  116.          small_eiffel.is_ready
  117.       deferred
  118.       end;
  119.  
  120.    frozen is_once_routine: BOOLEAN is
  121.       do
  122.      Result := is_once_function or else is_once_procedure;
  123.       end;
  124.  
  125.    frozen use_current: BOOLEAN is
  126.       require
  127.          small_eiffel.is_ready
  128.       do
  129.          inspect
  130.             use_current_state
  131.          when ucs_true then
  132.             Result := true;
  133.          when ucs_false then
  134.          when ucs_not_computed then
  135.             use_current_state := ucs_in_computation;
  136.             compute_use_current;
  137.             Result := use_current_state = ucs_true;
  138.          when ucs_in_computation then
  139.             Result := true;
  140.          end;
  141.       end;
  142.  
  143.    frozen stupid_switch(r: ARRAY[RUN_CLASS]): STRING is
  144.          -- Non-Void `Result' indicates a `stupid_switch' as well as the very 
  145.          -- nature of the stupid call site in order to print the 
  146.          -- associated comment in the generated C code.
  147.       require
  148.          run_control.boost;
  149.          small_eiffel.same_base_feature(Current,r)
  150.       do
  151.          check
  152.             -- Must always be called with the same array of run classes.
  153.             r = current_type.run_class.running
  154.          end;
  155.          inspect
  156.             stupid_switch_state
  157.          when ucs_true then
  158.             Result := stupid_switch_comment;
  159.          when ucs_false then
  160.          when ucs_not_computed then
  161.             stupid_switch_state := ucs_in_computation;
  162.             compute_stupid_switch(r);
  163.             if stupid_switch_state = ucs_true then
  164.                Result := stupid_switch_comment;
  165.             end;
  166.          when ucs_in_computation then
  167.          end;
  168.       end;
  169.  
  170.    fall_down is
  171.       local
  172.          running: ARRAY[RUN_CLASS];
  173.          i: INTEGER;
  174.          current_rc, sub_rc: RUN_CLASS;
  175.          current_bc, sub_bc: BASE_CLASS;
  176.          sub_name: FEATURE_NAME;
  177.          rf: RUN_FEATURE;
  178.       do
  179.          current_rc := current_type.run_class;
  180.          running := current_rc.running;
  181.          if running /= Void then
  182.             from
  183.                current_bc := current_type.base_class;
  184.                i := running.lower;
  185.             until
  186.                i > running.upper
  187.             loop
  188.                sub_rc := running.item(i);
  189.                if sub_rc /= current_rc then
  190.                   sub_bc := sub_rc.current_type.base_class;
  191.                   sub_name := sub_bc.new_name_of(current_bc,name);
  192.                   rf := sub_rc.get_feature(sub_name);
  193.                end;
  194.                i := i + 1;
  195.             end;
  196.          end;
  197.       end;
  198.  
  199.    afd_check is
  200.       deferred
  201.       end;
  202.  
  203.    frozen is_exported_in(cn: CLASS_NAME): BOOLEAN is
  204.          -- True if using of the receiver is legal when written in `cn'.
  205.          -- When false, `eh' is updated with the beginning of the
  206.          -- error message.
  207.       require
  208.          cn /= Void
  209.       do
  210.          Result := clients.gives_permission_to(cn);
  211.       end;
  212.  
  213.    frozen start_position: POSITION is
  214.       do
  215.          Result := base_feature.start_position;
  216.       end;
  217.  
  218.    frozen run_class: RUN_CLASS is
  219.       do
  220.          Result := current_type.run_class;
  221.       end;
  222.  
  223.    c_define is
  224.          -- Produce C code for definition.
  225.       require
  226.          cpp.on_c
  227.       deferred
  228.       ensure
  229.          cpp.on_c
  230.       end;
  231.  
  232.    mapping_c is
  233.          -- Produce C code when current is called and when the
  234.          -- concrete type of target is unique (`cpp' is in charge
  235.          -- of the context).
  236.       require
  237.          cpp.on_c
  238.       deferred
  239.       ensure
  240.          cpp.on_c
  241.       end;
  242.  
  243.    mapping_jvm is
  244.       deferred
  245.       end;
  246.  
  247.    frozen id: INTEGER is
  248.       do
  249.          Result := current_type.id;
  250.       end;
  251.  
  252.    mapping_name is
  253.       do
  254.          c_code.clear;
  255.          c_code.extend('r');
  256.          id.append_in(c_code);
  257.          name.mapping_c_in(c_code);
  258.          cpp.put_string(c_code);
  259.       end;
  260.  
  261.    frozen jvm_max_locals: INTEGER is
  262.       do
  263.          Result := current_type.jvm_stack_space;
  264.          if arguments /= Void then
  265.             Result := Result + arguments.jvm_stack_space;
  266.          end;
  267.          if local_vars /= Void then
  268.             Result := Result + local_vars.jvm_stack_space;
  269.          end;
  270.          if result_type /= Void then
  271.             Result := Result + result_type.jvm_stack_space;
  272.          end;
  273.       end;
  274.  
  275. feature {CALL}
  276.  
  277.    frozen vape_check_from(call_site: POSITION) is
  278.          -- Check VAPE rule for this `call_site'.
  279.       require
  280.          not call_site.is_unknown
  281.       do
  282.          small_eiffel.top_rf.clients.vape_check(call_site,clients);
  283.       end;
  284.  
  285. feature {ADDRESS_OF_POOL}
  286.  
  287.    address_of_c_define(caller: ADDRESS_OF) is
  288.          -- Corresponding `caller' is used for error messages.
  289.       require
  290.          caller /= Void
  291.       deferred
  292.       end;
  293.  
  294. feature {ADDRESS_OF}
  295.  
  296.    address_of_c_mapping is
  297.          -- Produce C code for operator $<feature_name>
  298.       require
  299.          run_class.at_run_time;
  300.          cpp.on_c
  301.       deferred
  302.       ensure
  303.          cpp.on_c
  304.       end;
  305.  
  306. feature {EXPRESSION}
  307.  
  308.    is_static: BOOLEAN is
  309.       require
  310.          small_eiffel.is_ready
  311.       deferred
  312.       end;
  313.  
  314.    static_value_mem: INTEGER is
  315.       require
  316.          is_static;
  317.       deferred
  318.       end;
  319.  
  320. feature 
  321.  
  322.    collect_c_tmp is
  323.      -- Collect needed temporary for user expanded.
  324.       deferred
  325.       end;
  326.  
  327. feature {E_RETRY,ASSERTION_LIST}
  328.  
  329.    c_assertion_flag is
  330.       do
  331.          c_code.clear;
  332.          c_frame_descriptor_name_in(c_code);
  333.          c_code.append(".assertion_flag");
  334.          cpp.put_string(c_code);
  335.       end;
  336.  
  337. feature {NATIVE}
  338.  
  339.    frozen default_mapping_procedure is
  340.          -- Default mapping for procedure calls with target.
  341.       do
  342.          default_mapping_function;
  343.          cpp.put_string(fz_00);
  344.       end;
  345.  
  346.    frozen default_mapping_function is
  347.          -- Default mapping for function calls with target.
  348.       local
  349.          no_check, uc, tcbd: BOOLEAN;
  350.       do
  351.          no_check := run_control.no_check;
  352.          uc := use_current;
  353.          if not uc then
  354.             tcbd := cpp.target_cannot_be_dropped;
  355.             if tcbd then
  356.                cpp.put_character(',');
  357.             end;
  358.          end;
  359.          mapping_name;
  360.          cpp.put_character('(');
  361.          if no_check then
  362.             cpp.put_string("&ds");
  363.          end;
  364.          if uc then
  365.             if no_check then
  366.                cpp.put_character(',');
  367.             end;
  368.             cpp.put_target_as_target;
  369.          end;
  370.          if arguments /= Void then
  371.             if uc or else no_check then
  372.                cpp.put_character(',');
  373.             end;
  374.             cpp.put_arguments;
  375.          end;
  376.          cpp.put_character(')');
  377.          if not uc and then tcbd then
  378.             cpp.put_character(')');
  379.          end;
  380.       end;
  381.  
  382.    routine_mapping_jvm is
  383.       local
  384.          rt, ct: TYPE;
  385.          idx, stack_level: INTEGER;
  386.       do
  387.          ct := current_type;
  388.          jvm.push_target_as_target;
  389.          stack_level := -(1 + jvm.push_arguments);
  390.          rt := result_type;
  391.          if rt /= Void then
  392.             stack_level := stack_level + rt.jvm_stack_space;
  393.          end
  394.          idx := constant_pool.idx_methodref(Current);
  395.          ct.run_class.jvm_invoke(idx,stack_level);
  396.       end;
  397.  
  398.    frozen c_define_with_body(body: STRING) is
  399.       require
  400.          body /= Void
  401.       do
  402.          define_prototype;
  403.          c_define_opening;
  404.          cpp.put_string(body);
  405.          c_define_closing;
  406.          if result_type = Void then
  407.             cpp.put_string(fz_12);
  408.          else
  409.             cpp.put_string(fz_15);
  410.          end;
  411.          c_frame_descriptor;
  412.       end;
  413.  
  414. feature {RUN_CLASS}
  415.  
  416.    jvm_field_or_method is
  417.          -- Update jvm's `fields' or `methods' if needed.
  418.       deferred
  419.       end;
  420.  
  421. feature {CONSTANT_POOL,SWITCH_COLLECTION}
  422.  
  423.    frozen jvm_descriptor: STRING is
  424.       do
  425.          tmp_jvm_descriptor.clear;
  426.          update_tmp_jvm_descriptor;
  427.          Result := tmp_jvm_descriptor;
  428.       end;
  429.  
  430. feature {JVM,ORDINARY_RESULT}
  431.  
  432.    frozen jvm_result_offset: INTEGER is
  433.          -- Offset of the Result local variable if any.
  434.       require
  435.          result_type /= Void
  436.       do
  437.          Result := current_type.jvm_stack_space;
  438.          if arguments /= Void then
  439.             Result := Result + arguments.jvm_stack_space;
  440.          end;
  441.          if local_vars /= Void then
  442.             Result := Result + local_vars.jvm_stack_space;
  443.          end;
  444.       end;
  445.  
  446. feature {JVM}
  447.  
  448.    jvm_define is
  449.          -- To compute the constant pool, the number of fields,
  450.          -- the number of methods, etc.
  451.       require
  452.          small_eiffel.is_ready
  453.       deferred
  454.       end;
  455.  
  456.    frozen jvm_argument_offset(a: ARGUMENT_NAME): INTEGER is
  457.       require
  458.          arguments /= Void
  459.       do
  460.          Result := current_type.jvm_stack_space;
  461.          Result := Result + arguments.jvm_offset_of(a);
  462.       ensure
  463.          Result >= a.rank - 1
  464.       end;
  465.  
  466.    frozen jvm_local_variable_offset(ln: LOCAL_NAME): INTEGER is
  467.       require
  468.          local_vars /= Void
  469.       do
  470.          Result := current_type.jvm_stack_space;
  471.          if arguments /= Void then
  472.             Result := Result + arguments.jvm_stack_space;
  473.          end;
  474.          Result := Result + local_vars.jvm_offset_of(ln);
  475.       ensure
  476.          Result >= ln.rank - 1
  477.       end;
  478.  
  479. feature {ONCE_RESULT}
  480.  
  481.    fe_vffd7 is
  482.       do
  483.          eh.add_position(result_type.start_position);
  484.          fatal_error("Result type of a once function must %
  485.                      %not be anchored (VFFD.7).");
  486.       end;
  487.  
  488. feature {RUN_FEATURE}
  489.  
  490.    is_in_computation: BOOLEAN is
  491.       do
  492.          Result := use_current_state = ucs_in_computation;
  493.       end;
  494.  
  495.    clients: like clients_memory is
  496.          -- Effective client list for the receiver (inherited "export"
  497.          -- clauses are also considered)..
  498.       local
  499.          bc, bfbc: BASE_CLASS;
  500.       do
  501.          if clients_memory = Void then
  502.             bc := current_type.base_class;
  503.             bfbc := base_feature.base_class;
  504.             if bc = bfbc then
  505.                Result := base_feature.clients;
  506.             else
  507.                check
  508.                   bc.is_subclass_of(bfbc)
  509.                end;
  510.                Result := bc.clients_for(name);
  511.             end;
  512.             clients_memory := Result;
  513.          else
  514.             Result := clients_memory;
  515.          end;
  516.       ensure
  517.          Result /= Void
  518.       end;
  519.  
  520. feature {NATIVE_C_PLUS_PLUS}
  521.  
  522.    c_plus_plus_prototype(er: EXTERNAL_ROUTINE) is
  523.       require
  524.          er = base_feature
  525.       local
  526.      comment: STRING;
  527.       do
  528.      comment := "....................";
  529.      comment.copy(fz_open_c_comment);
  530.      comment.append("C++ wrapper for ");
  531.      comment.append(er.base_class.name.to_string);
  532.      comment.extend('.');
  533.      comment.append(name.to_string);
  534.      comment.append(fz_close_c_comment);
  535.      comment.extend('%N');
  536.          external_prototype_for(comment,er);
  537.          cpp.put_c_heading(c_code);
  538.       end;
  539.  
  540. feature {NONE}
  541.  
  542.    compute_stupid_switch(r: ARRAY[RUN_CLASS]) is
  543.       require
  544.          stupid_switch_state = ucs_in_computation
  545.       deferred
  546.       ensure
  547.          stupid_switch_state = ucs_true or else stupid_switch_state = ucs_false
  548.       end;
  549.  
  550.    frozen external_prototype_for(tag: STRING; er: EXTERNAL_ROUTINE) is
  551.       local
  552.          t: TYPE;
  553.       do
  554.          c_code.clear;
  555.          c_code.append(tag);
  556.          -- Define heading of corresponding C function.
  557.          t := result_type;
  558.          if t = Void then
  559.             c_code.append(fz_void);
  560.          else
  561.             t.c_type_for_external_in(c_code);
  562.          end;
  563.          c_code.extend(' ');
  564.          c_code.append(er.external_c_name);
  565.          c_code.extend('(');
  566.          if er.use_current then
  567.             current_type.c_type_for_external_in(c_code);
  568.             c_code.extend(' ');
  569.             c_code.extend('C');
  570.             if arguments /= Void then
  571.                c_code.extend(',');
  572.             end;
  573.          end;
  574.          if arguments = Void then
  575.             if not er.use_current then
  576.                c_code.append(fz_void);
  577.             end;
  578.          else
  579.             arguments.external_prototype_in(c_code);
  580.          end;
  581.          c_code.extend(')');
  582.       end;
  583.  
  584.    frozen put_c_name_tag is
  585.       require
  586.          run_control.no_check
  587.       local
  588.          fn: FEATURE_NAME;
  589.       do
  590.          cpp.put_character('%"');
  591.          fn := base_feature.first_name;
  592.          if fn.to_key /= name.to_key then
  593.             name.put_cpp_tag;
  594.             cpp.put_string(name.to_string);
  595.             cpp.put_character(' ');
  596.             cpp.put_character('(');
  597.          end;
  598.          fn.put_cpp_tag;
  599.          cpp.put_string(fn.to_string);
  600.          cpp.put_string(" of ");
  601.          cpp.put_string(base_feature.base_class_name.to_string);
  602.          if fn.to_key /= name.to_key then
  603.             cpp.put_character(')');
  604.          end;
  605.          cpp.put_character('%"');
  606.       end;
  607.  
  608.    frozen run_require: RUN_REQUIRE is
  609.       do
  610.          Result := current_type.base_class.run_require(Current);
  611.       end;
  612.  
  613.    frozen run_ensure: E_ENSURE is
  614.       do
  615.          Result := current_type.base_class.run_ensure(Current);
  616.       end;
  617.  
  618.    address_of_wrapper_name_in(str: STRING) is
  619.       do
  620.          str.extend('W');
  621.          id.append_in(str);
  622.          name.mapping_c_in(str);
  623.       end;
  624.  
  625.    address_of_c_define_wrapper(caller: ADDRESS_OF) is
  626.       require
  627.          cpp.on_c
  628.       do
  629.          c_code.clear;
  630.          if result_type = Void then
  631.             c_code.append(fz_void);
  632.          else
  633.             result_type.c_type_for_external_in(c_code);
  634.          end;
  635.          c_code.extend(' ');
  636.          address_of_wrapper_name_in(c_code);
  637.          c_code.extend('(');
  638.          current_type.c_type_for_external_in(c_code);
  639.          c_code.extend(' ');
  640.          c_code.extend('C');
  641.          if arguments /= Void then
  642.             c_code.extend(',');
  643.             arguments.external_prototype_in(c_code);
  644.          end;
  645.          c_code.extend(')');
  646.          cpp.put_c_heading(c_code);
  647.          cecil_pool.define_body_of(Current);
  648.       end;
  649.  
  650.    address_of_c_mapping_wrapper is
  651.       do
  652.          c_code.clear;
  653.          address_of_wrapper_name_in(c_code);
  654.          cpp.put_string(c_code);
  655.       end;
  656.  
  657.    c_frame_descriptor_name_in(str: STRING) is
  658.       do
  659.          str.extend('f');
  660.          id.append_in(str);
  661.          name.mapping_c_in(str);
  662.       end;
  663.  
  664.    c_frame_descriptor is
  665.       do
  666.          if run_control.no_check then
  667.             c_code.copy("se_frame_descriptor ");
  668.             c_frame_descriptor_name_in(c_code);
  669.             cpp.put_extern7(c_code);
  670.             cpp.put_character('{');
  671.             put_c_name_tag;
  672.             c_code.clear;
  673.             c_code.extend(',');
  674.             if use_current then
  675.                c_code.extend('1');
  676.             else
  677.                c_code.extend('0');
  678.             end;
  679.             c_code.extend(',');
  680.             c_frame_descriptor_local_count.append_in(c_code);
  681.             c_code.extend(',');
  682.             c_code.append(c_frame_descriptor_format);
  683.             c_code.append("%",1};%N");
  684.             cpp.put_string(c_code);
  685.          end;
  686.       end;
  687.  
  688.    define_prototype is
  689.       require
  690.          run_class.at_run_time;
  691.          cpp.on_c
  692.       local
  693.          mem_id: INTEGER;
  694.          no_check: BOOLEAN;
  695.       do
  696.          no_check := run_control.no_check;
  697.          if run_control.no_check then
  698.             c_frame_descriptor_local_count.reset;
  699.             c_frame_descriptor_format.clear;
  700.             c_frame_descriptor_format.extend('%"');
  701.             c_frame_descriptor_locals.clear;
  702.          end;
  703.          mem_id := id;
  704.          -- Define heading of corresponding C function.
  705.          c_code.clear;
  706.      -- Extra comment to debug C code :
  707.      -- c_code.append("/*");
  708.      -- c_code.append(current_type.run_time_mark);
  709.      -- c_code.append("*/%N");
  710.      --
  711.          if result_type = Void then
  712.             c_code.append(fz_void);
  713.          else
  714.             result_type.run_type.c_type_for_result_in(c_code);
  715.          end;
  716.          c_code.extend(' ');
  717.          c_code.extend('r');
  718.          mem_id.append_in(c_code);
  719.          name.mapping_c_in(c_code);
  720.          c_code.extend('(');
  721.          if no_check then
  722.             c_code.append("se_dump_stack*caller");
  723.             if use_current or else arguments /= Void then
  724.                c_code.extend(',');
  725.             end;
  726.          end;
  727.          if use_current then
  728.             current_type.c_type_for_target_in(c_code);
  729.             c_code.extend(' ');
  730.             c_code.extend('C');
  731.             current_type.c_frame_descriptor;
  732.             if arguments /= Void then
  733.                c_code.extend(',');
  734.             end;
  735.          end;
  736.          if arguments = Void then
  737.             if no_check then
  738.             elseif not use_current then
  739.                c_code.append(fz_void);
  740.             end;
  741.          else
  742.             arguments.compile_to_c_in(c_code);
  743.          end;
  744.          c_code.extend(')');
  745.          cpp.put_c_heading(c_code);
  746.          cpp.swap_on_c;
  747.       ensure
  748.          cpp.on_c
  749.       end;
  750.  
  751.    c_define_opening is
  752.          -- Define opening section in C function.
  753.       local
  754.          t: TYPE;
  755.          no_check, ensure_check: BOOLEAN;
  756.      oresult: STRING;
  757.       do
  758.          no_check := run_control.no_check;
  759.          ensure_check := run_control.ensure_check;
  760.          -- (0) --------------------------- Exception handling :
  761.          if rescue_compound /= Void then
  762.             cpp.put_string("struct rescue_context rc;%N");
  763.          end;
  764.          -- (1) -------------------- Local variable for Result :
  765.          if is_once_function then
  766.             if no_check then
  767.                t := result_type.run_type;
  768.                c_frame_descriptor_locals.append("(void**)&");
  769.            oresult := once_routine_pool.o_result(base_feature);
  770.                c_frame_descriptor_locals.append(oresult);
  771.                c_frame_descriptor_locals.extend(',');
  772.                c_frame_descriptor_local_count.increment;
  773.                c_frame_descriptor_format.append(as_result);
  774.                t.c_frame_descriptor;
  775.             end;
  776.          elseif result_type /= Void then
  777.             t := result_type.run_type;
  778.             c_code.clear;
  779.             t.c_type_for_result_in(c_code);
  780.             c_code.append(" R=");
  781.             t.c_initialize_in(c_code);
  782.             c_code.append(fz_00);
  783.             cpp.put_string(c_code);
  784.             if no_check then
  785.                c_frame_descriptor_locals.append("(void**)&R,");
  786.                c_frame_descriptor_local_count.increment;
  787.                c_frame_descriptor_format.append(as_result);
  788.                t.c_frame_descriptor;
  789.             end;
  790.          end;
  791.          -- (2) ----------------------- User's local variables :
  792.          if local_vars /= Void then
  793.             local_vars.c_declare;
  794.          end;
  795.          -- (3) ---------------- Local variable for old/ensure :
  796.          if ensure_check then
  797.             if ensure_assertion /= Void then
  798.                ensure_assertion.c_declare_for_old;
  799.             end;
  800.          end;
  801.          if no_check then
  802.          -- (4) ------------------------------- Prepare locals :
  803.             if c_frame_descriptor_local_count.value > 0 then
  804.                c_code.copy("void**locals[");
  805.                c_frame_descriptor_local_count.append_in(c_code);
  806.                c_code.extend(']');
  807.                c_code.append(fz_00);
  808.                cpp.put_string(c_code);
  809.             end;
  810.          -- (5) ----------------------------------- Prepare ds :
  811.             c_initialize_ds_one_by_one;
  812.             c_initialize_locals_one_by_one;
  813.          -- (6) ------------------------ Initialise Dump Stack :
  814.             cpp.put_string("se_dst=&ds;/*link*/%N");
  815.          end;
  816.          -- (7) ----------------------- Execute old for ensure :
  817.          if ensure_check then
  818.             if ensure_assertion /= Void then
  819.                ensure_assertion.compile_to_c_old;
  820.             end;
  821.          end;
  822.          -- (8) --------------------------- Exception handling :
  823.          if rescue_compound /= Void then
  824.             cpp.put_string("if(SETJMP(rc.jb)!=0){/*rescue*/%N");
  825.             rescue_compound.compile_to_c;
  826.             cpp.put_string("internal_exception_handler(Routine_failure);%N}%N");
  827.          end;
  828.          -- (9) -------------------- Initialize local expanded :
  829.          if local_vars /= Void then
  830.             local_vars.initialize_expanded;
  831.          end;
  832.          -- (10) --------------------------- Retry start label :
  833.          if rescue_compound /= Void then
  834.             cpp.put_string("retry_tag:%N");
  835.          end;
  836.          -- (11) ---------------------- Require assertion code :
  837.          if require_assertion /= Void then
  838.             require_assertion.compile_to_c;
  839.          end;
  840.          -- (12) ------------------------- Save rescue context :
  841.          if rescue_compound /= Void then
  842.             cpp.put_string("rc.next = rescue_context_top;%N%
  843.                            %rescue_context_top = &rc;%N");
  844.             if no_check then
  845.            cpp.put_string("rc.top_of_ds=&ds;%N");
  846.                cpp.put_string("se_dst=&ds;/*link*/%N");
  847.             end;
  848.          end;
  849.       end;
  850.  
  851.    c_define_closing is
  852.          -- Define closing section in C function :
  853.          --    - code for ensure checking.
  854.          --    - free memory of expanded.
  855.          --    - run stack pop.
  856.       do
  857.          -- (1) --------------------------- Ensure Check Code :
  858.          if run_control.ensure_check then
  859.             if ensure_assertion /= Void then
  860.                ensure_assertion.compile_to_c;
  861.             end;
  862.          end;
  863.          -- (2) ----------------------------- Class Invariant :
  864.          if use_current then
  865.         if name.to_string /= as_dispose then
  866.            cpp.current_class_invariant(current_type);
  867.         end;
  868.          end;
  869.          -- (3) ---------------------------------- For rescue :
  870.          if rescue_compound /= Void then
  871.             cpp.put_string("rescue_context_top = rc.next;%N");
  872.          end;
  873.          -- (4) ------------------------------- Run Stack Pop :
  874.          if run_control.no_check then
  875.             cpp.put_string("se_dst=caller;/*unlink*/%N");
  876.          end;
  877.       end;
  878.  
  879.    external_prototype(er: EXTERNAL_ROUTINE) is
  880.          -- Define prototype for an external routine.
  881.       require
  882.          er = base_feature
  883.       do
  884.          external_prototype_for("/*external*/",er);
  885.          c_code.append(fz_00);
  886.          cpp.swap_on_h;
  887.          cpp.put_string(c_code);
  888.          cpp.swap_on_c;
  889.       ensure
  890.          cpp.on_c
  891.       end;
  892.  
  893.    use_current_state: INTEGER;
  894.    
  895.    stupid_switch_state: INTEGER;
  896.  
  897.    ucs_false, ucs_true, ucs_not_computed, 
  898.    ucs_in_computation: INTEGER is unique;
  899.  
  900.    frozen std_compute_use_current is
  901.       require
  902.          is_in_computation
  903.       do
  904.          if use_current_state = ucs_in_computation then
  905.             if require_assertion /= Void then
  906.                if require_assertion.use_current then
  907.                   use_current_state := ucs_true;
  908.                end;
  909.             end;
  910.          end;
  911.          if use_current_state = ucs_in_computation then
  912.             if routine_body /= Void then
  913.                if routine_body.use_current then
  914.                   use_current_state := ucs_true;
  915.                end;
  916.             end;
  917.          end;
  918.          if use_current_state = ucs_in_computation then
  919.             if rescue_compound /= Void then
  920.                if rescue_compound.use_current then
  921.                   use_current_state := ucs_true;
  922.                end;
  923.             end;
  924.          end;
  925.          if use_current_state = ucs_in_computation then
  926.             if ensure_assertion /= Void then
  927.                if ensure_assertion.use_current then
  928.                   use_current_state := ucs_true;
  929.                end;
  930.             end;
  931.          end;
  932.          if use_current_state = ucs_in_computation then
  933.             use_current_state := ucs_false;
  934.          end;
  935.       ensure
  936.          use_current_state = ucs_false or else
  937.          use_current_state = ucs_true;
  938.       end;
  939.  
  940.    compute_use_current is
  941.       require
  942.          is_in_computation
  943.       deferred
  944.       ensure
  945.          use_current_state = ucs_true or else
  946.          use_current_state = ucs_false;
  947.       end;
  948.  
  949.    frozen std_compute_stupid_switch(r: ARRAY[RUN_CLASS]) is
  950.       require
  951.          stupid_switch_state = ucs_in_computation
  952.       local
  953.          rt: TYPE;
  954.       do
  955.          check
  956.             small_eiffel.same_base_feature(Current,r)
  957.          end;
  958.          rt := result_type;
  959.          if rt /= Void and then rt.is_user_expanded then
  960.             stupid_switch_state := ucs_false;
  961.          end;
  962.          if stupid_switch_state = ucs_in_computation then
  963.             if routine_body /= Void then
  964.                if not routine_body.stupid_switch(r) then
  965.                   stupid_switch_state := ucs_false;
  966.                end;
  967.             end;
  968.          end;
  969.          if stupid_switch_state = ucs_in_computation then
  970.             if rescue_compound /= Void then
  971.                if not rescue_compound.stupid_switch(r) then
  972.                   stupid_switch_state := ucs_false;
  973.                end;
  974.             end;
  975.          end;
  976.          if stupid_switch_state = ucs_in_computation then
  977.             stupid_switch_state := ucs_true;
  978.          end;
  979.       ensure
  980.          stupid_switch_state = ucs_true or stupid_switch_state = ucs_false;
  981.       end;
  982.  
  983.    c_code: STRING is
  984.       once
  985.      !!Result.make(512);
  986.       end;
  987.  
  988.    update_tmp_jvm_descriptor is
  989.       deferred
  990.       end;
  991.  
  992.    tmp_jvm_descriptor: STRING is
  993.       once
  994.          !!Result.make(128);
  995.       end;
  996.  
  997.    routine_update_tmp_jvm_descriptor is
  998.          -- For RUN_FEATURE_3/4/5/6/7/8/9/10/11 :
  999.       local
  1000.          ct, rt: TYPE;
  1001.       do
  1002.          tmp_jvm_descriptor.extend('(');
  1003.          ct := current_type;
  1004.          ct.jvm_target_descriptor_in(tmp_jvm_descriptor);
  1005.          if arguments /= Void then
  1006.             arguments.jvm_descriptor_in(tmp_jvm_descriptor);
  1007.          end;
  1008.          rt := result_type;
  1009.          if rt = Void then
  1010.             tmp_jvm_descriptor.append(fz_19);
  1011.          else
  1012.             rt := rt.run_type;
  1013.             tmp_jvm_descriptor.extend(')');
  1014.             rt.jvm_descriptor_in(tmp_jvm_descriptor);
  1015.          end;
  1016.       end;
  1017.  
  1018.    method_info_start is
  1019.       local
  1020.          flags: INTEGER;
  1021.       do
  1022.          flags := current_type.jvm_method_flags;
  1023.          method_info.start(flags,name.to_key,jvm_descriptor);
  1024.       end;
  1025.  
  1026.    jvm_define_opening is
  1027.       require
  1028.          jvm.current_frame = Current
  1029.       local
  1030.          space: INTEGER;
  1031.       do
  1032.          -- (1) -------------------- Local variable for Result :
  1033.          if result_type /= Void then
  1034.             space := result_type.jvm_push_default;
  1035.         if is_once_function then 
  1036.            once_routine_pool.jvm_result_store(Current);
  1037.         else
  1038.            result_type.jvm_write_local(jvm_result_offset);
  1039.         end;
  1040.          end;
  1041.          -- (2) ----------------------- User's local variables :
  1042.          if local_vars /= Void then
  1043.             local_vars.jvm_initialize;
  1044.          end;
  1045.          -- (3) ---------------- Local variable for old/ensure :
  1046.          if run_control.ensure_check then
  1047.             if ensure_assertion /= Void then
  1048.                ensure_assertion.compile_to_jvm_old;
  1049.             end;
  1050.          end;
  1051.          -- (4) ----------------------- Require assertion code :
  1052.          if require_assertion /= Void then
  1053.             require_assertion.compile_to_jvm;
  1054.          end;
  1055.       end;
  1056.  
  1057.    jvm_define_closing is
  1058.       require
  1059.          jvm.current_frame = Current
  1060.       do
  1061.          -- (0) ----------------------------- Class Invariant :
  1062.          -- (1) --------------------------- Ensure Check Code :
  1063.          if run_control.ensure_check then
  1064.             if ensure_assertion /= Void then
  1065.                ensure_assertion.compile_to_jvm(true);
  1066.                code_attribute.opcode_pop;
  1067.             end;
  1068.          end;
  1069.          -- (2) --------------------- Free for local expanded :
  1070.       end;
  1071.  
  1072.    routine_afd_check is
  1073.       do
  1074.          if require_assertion /= Void then
  1075.             require_assertion.afd_check;
  1076.          end;
  1077.          if routine_body /= Void then
  1078.             routine_body.afd_check;
  1079.          end;
  1080.          if rescue_compound /= Void then
  1081.             rescue_compound.afd_check;
  1082.          end;
  1083.          if ensure_assertion /= Void then
  1084.             ensure_assertion.afd_check;
  1085.          end;
  1086.       end;
  1087.  
  1088.    c_initialize_ds_one_by_one is
  1089.       require
  1090.          run_control.no_check
  1091.       do
  1092.          c_code.copy("se_dump_stack ds;%Nds.fd=&");
  1093.          c_frame_descriptor_name_in(c_code);
  1094.          c_code.append(fz_00);
  1095.          if use_current then
  1096.             c_code.append("ds.current=((void**)&C);%N");
  1097.          else
  1098.             c_code.append("ds.current=NULL;%N");
  1099.          end;
  1100.          cpp.put_string(c_code);
  1101.          cpp.put_position_in_ds(start_position);
  1102.          cpp.put_string("ds.caller=caller;%N");
  1103.          if c_frame_descriptor_local_count.value > 0 then
  1104.             cpp.put_string("ds.locals=locals;%N");
  1105.          end;
  1106.       end;
  1107.  
  1108.    c_initialize_locals_one_by_one is
  1109.       require
  1110.          run_control.no_check
  1111.       local
  1112.          i, j: INTEGER;
  1113.          c: CHARACTER;
  1114.       do
  1115.          from
  1116.             j := 1;
  1117.          until
  1118.             c_frame_descriptor_local_count.value = i
  1119.          loop
  1120.             cpp.put_string("locals[");
  1121.             cpp.put_integer(i);
  1122.             cpp.put_string("]=");
  1123.             from
  1124.                c := c_frame_descriptor_locals.item(j);
  1125.             until
  1126.                c = ','
  1127.             loop
  1128.                cpp.put_character(c);
  1129.                j := j + 1;
  1130.                c := c_frame_descriptor_locals.item(j);
  1131.             end;
  1132.             j := j + 1;
  1133.             cpp.put_string(fz_00);
  1134.             i := i + 1;
  1135.          end;
  1136.       end;
  1137.  
  1138.    initialize is
  1139.          -- Perform carefully the initialization (must not trigger
  1140.          -- another `initialize').
  1141.       deferred
  1142.       end;
  1143.  
  1144.    frozen default_rescue_compound: COMPOUND is
  1145.          -- Builds and returns an "artificial" compound that simply 
  1146.          -- calls `default_rescue'.
  1147.          -- If the `default_rescue' routine is from GENERAL, then no 
  1148.          -- compound is built and Void is returned, so as to avoid 
  1149.          -- generation of costly SETJMP/LONGJMPs.
  1150.       do
  1151.          Result := run_class.get_default_rescue(name);
  1152.       end;
  1153.    
  1154.    frozen make(t: like current_type; n: like name; bf: like base_feature) is
  1155.       require
  1156.          t.run_type = t;
  1157.          n /= Void;
  1158.          bf /= void;
  1159.          not small_eiffel.is_ready
  1160.       local
  1161.      debug_info: STRING;
  1162.       do
  1163.      debug
  1164.         debug_info := t.run_time_mark.twin;
  1165.         debug_info.extend('.');
  1166.         debug_info.append(n.to_string.twin);
  1167.      end;
  1168.          current_type := t;
  1169.          name := n;
  1170.          base_feature := bf;
  1171.          run_class.add_rf(Current,n.to_key);
  1172.          small_eiffel.incr_magic_count;
  1173.          use_current_state := ucs_not_computed;
  1174.          stupid_switch_state := ucs_not_computed;
  1175.          small_eiffel.push(Current);
  1176.          initialize;
  1177.          small_eiffel.pop;
  1178.       ensure
  1179.          run_class.get_feature(name) = Current
  1180.       end;
  1181.  
  1182.    stupid_switch_comment: STRING is
  1183.       deferred
  1184.       end;
  1185.  
  1186. invariant
  1187.  
  1188.    current_type /= Void;
  1189.  
  1190.    name /= Void;
  1191.  
  1192.    base_feature /= Void;
  1193.  
  1194. end -- RUN_FEATURE
  1195.  
  1196.